<!-- 下拉标签组件 -->
<template>
    <div class="drop-tabs-wp">
        <div class="prev-box">
            <slot name="prev"></slot>
        </div>
        <div class="list-wrapper" :style="{height: getSize(height)}">
            <div ref="scroll" class="list-scroll" 
                @scroll="handleScroll"
                @wheel.prevent="onWheel">
                <div ref="list" class="list-line" :style="{
                    gap: getSize(gap),
                    width: listWidth+'px',
                }">
                    <div v-for="(item, index) in list" :key="index" class="list-item" @click="changeActive(item)">
                        <slot name="tab" v-bind="item"></slot>
                    </div>
                </div>
            </div>
        </div>
        <div v-if="dropList.length" class="drag-box">
            <el-dropdown>
                <slot name="drapbtn"></slot>
                <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item v-for="(item, index) in dropList" :key="index" @click.native="changeActive(item)">{{ item.label }}</el-dropdown-item>
                </el-dropdown-menu>
            </el-dropdown>
        </div>
    </div>
</template>
<script>
export default {
    model: {
        prop: 'value',
        event: 'change'
    },
    props: {
        value: {
            type: [String, Number],
            default: ''
        },
        list: {
            type: Array,
            default: () => []
        },
        // 间隔
        gap: {
            type: [String, Number],
            default: 0
        },
        // 高度
        height: {
            type: [String, Number],
            default: 0
        },
    },
    data() {
        return {
            ob: null,

            listWidth: '',

            dropList: [],
            timer: null,
        };
    },
    mounted() {
        // 创建观察对象
        this.ob = new MutationObserver(() => {
            // 调用事件通知父组件
            this.$nextTick(this.updateSizes);
        })
        this.ob.observe(this.$refs.list, { childList: true, subtree: true });
        this.$nextTick(this.updateSizes);
    },
    methods: {
        // 计算尺寸
        updateSizes() {
            const gapW = parseFloat(this.gap);

            const slotNodes = this.$refs.list.childNodes;
            let listW = 0;
            for(let i = 0; i < slotNodes.length; i++) {
                const item = slotNodes[i];
                if(item.nodeType === 1) {
                    listW += item.offsetWidth + gapW;
                }
            }
            listW -= gapW;
            this.listWidth = listW + 1;

            // 列表宽度更新后，判断tab位置
            this.$nextTick(() => {
                this.getTabPosition();
            })
        },

        // 判断每一个tab的位置，决定是否显示省略号
        getTabPosition() {
            const arr = []; 

            this.list.forEach((item, index) => {
                let left = this.getScrollLeft(index);
                if(left !== false) {
                    arr.push(this.list[index]);
                }
            })

            this.dropList = arr;
        },

        getSize(val) {
            if(typeof val == 'number') {
                return val + 'px';
            }
            return val;
        },
        
        changeActive(item) {
            this.$emit('change', item.value);

            let index = this.list.findIndex((v) => v.value == item.value);
            let left = this.getScrollLeft(index);

            if(left !== false) {
                this.$refs.scroll.scrollTo({
                    left: left,
                    behavior: 'smooth'
                });
            }
        },

        // 判断dom是否在内容区域
        getScrollLeft(index) {
            // 所有dom节点
            const tabs = this.$refs.list.childNodes;
            // 容器滚动距离
            const cSL = this.$refs.scroll.scrollLeft;
            // 容器宽度
            const cW = this.$refs.scroll.clientWidth;
            // 计算滚动位置
            let oTab = tabs[index];
            let oW = oTab.clientWidth;
            let oL = oTab.offsetLeft;
            if(cSL > oL) {
                return oL;
            } else if(cSL + cW < oL + oW) {
                return oL + oW - cW;
            }
            return false;
        },

        handleScroll() {
            clearTimeout(this.timer);
            this.timer = setTimeout(() => {
                this.getTabPosition();
            }, 100);
        },

        onWheel(e) {
            // 鼠标滚轮横向滚动
            const delta = e.deltaY || e.deltaX;
            if (delta === 0) return;
            
            let cSL = this.$refs.scroll.scrollLeft;
            let next = delta > 0 ? cSL+30 : cSL-30;
            
            this.$refs.scroll.scrollTo({
                left: next
            })
        },
    }
};
</script>
<style scoped lang='scss'>
.drop-tabs-wp {
    display: flex;
    width: 100%;
    .list-wrapper {
        flex: 1;
        width: 0;
        overflow: hidden;
        .list-scroll {
            overflow: auto;
            width: 100%;
        }
        .list-line {
            display: flex;
            flex-wrap: wrap;
            position: relative;
            .list-item {

            }
        }
    }
}
</style>